package at.jaki.ubb.crawling.dataTransformer;

import java.util.Collection;
import java.util.concurrent.Callable;

import org.apache.log4j.Logger;

import at.jaki.ubb.crawling.api.DataTransformer;
import at.jaki.ubb.crawling.appThreads.AbstractManagerWrapperThread;
import at.jaki.ubb.crawling.model.DataTransformerResult;
import at.jaki.ubb.crawling.model.RawData;

/**
 * A Wrapper class around the DataTransformer. The class implements the {@link Callable} interface, so it can be used in a multithreaded environment.
 * @author Attila Jakabfi
 *
 * @param <RD> generic type of the {@link RawData} element. 
 */
public class DataTransformerThread<RD> extends AbstractManagerWrapperThread<DataTransformerResult<?, ?, ?>>{
	
	private static final Logger LOG = Logger.getLogger(DataTransformerThread.class);

	private DataTransformer<?, ?, ?, RD> dataTransformer;
	private RawData<RD> data;
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public DataTransformerThread(String clazz) {
		try {
			Object instance = Class.forName(clazz).newInstance();
			dataTransformer = (DataTransformer) instance;
			dataTransformer.init();
		} catch (InstantiationException e) {
			LOG.error("Could not instantiate class ".concat(clazz).concat(". No default constuctor, or the class is abstract."));
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (IllegalAccessException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (ClassCastException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (RuntimeException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		}
	}
	
	public final void setData(RawData<RD> data) {
		this.data = data;
	}

	public final boolean isInitialized() {
		return dataTransformer != null;
	}

	public Collection<String> getTypes() {
		return dataTransformer.getTypes();
	}
	
	@Override
	public DataTransformerResult<?, ?, ?> doWork() throws Exception {
		return dataTransformer.transformData(data);
	}

}
